package com.yjq.yys.yhCalculate.service;

import com.yjq.yys.yhCalculate.dao.SsDao;
import com.yjq.yys.yhCalculate.dao.YhDao;
import com.yjq.yys.yhCalculate.dao.YhSortDao;
import com.yjq.yys.yhCalculate.dto.YhSelectDTO;
import com.yjq.yys.yhCalculate.entity.Yh;
import com.yjq.yys.yhCalculate.entity.YhSort;
import com.yjq.yys.yhCalculate.enums.BuffSortEnum;
import com.yjq.yys.yhCalculate.utils.Assert;
import com.yjq.yys.yhCalculate.utils.YhCalculateUtil;
import com.yjq.yys.yhCalculate.vo.YhCalculateVO;
import com.yjq.yys.yhCalculate.vo.YhExpectVO;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class YhService {

    @Resource
    private YhDao yhDao;

    @Resource
    private YhSortDao yhSortDao;

    @Resource
    private SsDao ssDao;

    @Transactional(rollbackFor = Exception.class)
    public String addByJson(String jsonStr, int userId) {
        jsonStr = jsonStr.substring(1);
        JSONArray jsonArray = JSONArray.fromObject(jsonStr);
        List<Map<String, Object>> mapListJson = (List) jsonArray;

        List<Yh> yhDbList = yhDao.listYh(YhSelectDTO.builder().userId(userId).build());
        Map<String, Integer> yhDbMap = yhDbList.stream().collect(Collectors.toMap(Yh::getNId, Yh::getId));
        Map<String, Integer> sortMap = yhSortDao.listYhSort().stream().collect(Collectors.toMap(YhSort::getName, YhSort::getId, (a, b) -> b));
        int total = 0;

        for (int i = 0; i < mapListJson.size(); i++) {

            Map<String, Object> obj = mapListJson.get(i);

            Yh yh = new Yh();
            yh.setIsUsable(true);
            yh.setIsDeleted(false);
            yh.setUserId(userId);

            for (Map.Entry<String, Object> entry : obj.entrySet()) {

                switch (entry.getKey()) {
                    case "御魂ID":
                        String nId = (String)entry.getValue();
                        yh.setNId(nId);
                        Integer id = yhDbMap.remove(nId);
                        if(id != null) {
                            yh.setId(id);
                            yhDbMap.remove(nId);
                        }
                        break;
                    case "御魂类型":
                        Integer yhSortId = sortMap.get((String)entry.getValue());
                        Assert.notNull(yhSortId, "未查询到御魂类型: " + entry.getValue());
                        yh.setYhSortId(yhSortId);
                        break;
                    case "位置":
                        Integer location = (Integer)entry.getValue();
                        yh.setLocation(location);
                        if (location == 1) {
                            yh.setMainBuff(BuffSortEnum.ATTACK.getIndex());
                            yh.setMainValue(486D);
                        } else if (location == 3) {
                            yh.setMainBuff(BuffSortEnum.DEFENCE.getIndex());
                            yh.setMainValue(104D);
                        } else if (location == 5) {
                            yh.setMainBuff(BuffSortEnum.HEALTH_POINT.getIndex());
                            yh.setMainValue(2052D);
                        }
                        break;
                    case "御魂等级":
                        yh.setLevel((Integer) entry.getValue());
                        break;
                    case "御魂星级":
                        yh.setStar((Integer) entry.getValue());
                        break;
                    case "攻击":
                        yh.setAttackValue((Double) entry.getValue());
                        break;
                    case "攻击加成":
                        Double attackRate = (Double) entry.getValue();
                        yh.setAttackRate(attackRate);
                        if(attackRate > 0.55) {
                            yh.setMainBuff(BuffSortEnum.ATTACK_RATE.getIndex());
                            yh.setMainValue(0.55);
                        }
                        break;
                    case "生命":
                        yh.setHealthPointValue((Double) entry.getValue());
                        break;
                    case "生命加成":
                        Double healthPoint = (Double) entry.getValue();
                        yh.setHealthPointRate(healthPoint);
                        if(healthPoint > 0.55) {
                            yh.setMainBuff(BuffSortEnum.HEALTH_POINT_RATE.getIndex());
                            yh.setMainValue(0.55);
                        }
                        break;
                    case "防御":
                        yh.setDefenceValue((Double) entry.getValue());
                        break;
                    case "防御加成":
                        Double defence = (Double) entry.getValue();
                        yh.setDefenceRate(defence);
                        if(defence > 0.55) {
                            yh.setMainBuff(BuffSortEnum.DEFENCE_RATE.getIndex());
                            yh.setMainValue(0.55);
                        }
                        break;
                    case "速度":
                        Double velocity = (Double) entry.getValue();
                        yh.setVelocity(velocity);
                        if(velocity > 57) {
                            yh.setMainBuff(BuffSortEnum.VELOCITY.getIndex());
                            yh.setMainValue(57D);
                        }
                        break;
                    case "暴击":
                        Double critRate = (Double) entry.getValue();
                        yh.setCritRate(critRate);
                        if(critRate > 0.55) {
                            yh.setMainBuff(BuffSortEnum.CRIT_RATE.getIndex());
                            yh.setMainValue(0.55);
                        }
                        break;
                    case "暴击伤害":
                        Double critDamage = (Double) entry.getValue();
                        yh.setCritDamage(critDamage);
                        if(critDamage > 0.89) {
                            yh.setMainBuff(BuffSortEnum.CRIT_DAMAGE.getIndex());
                            yh.setMainValue(0.89);
                        }
                        break;
                    case "效果命中":
                        Double effectHit = (Double) entry.getValue();
                        yh.setEffectHit(effectHit);
                        if(effectHit > 0.55) {
                            yh.setMainBuff(BuffSortEnum.EFFECT_HIT.getIndex());
                            yh.setMainValue(0.55);
                        }
                        break;
                    case "效果抵抗":
                        Double effectAvoid = (Double) entry.getValue();
                        yh.setEffectAvoid(effectAvoid);
                        if(effectAvoid > 0.55) {
                            yh.setMainBuff(BuffSortEnum.EFFECT_AVOID.getIndex());
                            yh.setMainValue(0.55);
                        }
                        break;
                    case "userId":
                        yh.setUserId(userId);
                        break;
                    case "固有属性":
                        break;
                    default:
                        System.out.println(entry.getKey() + "-不存在");
                }

            }
            if(yh.getId() == null) {
                total += yhDao.insertSelective(yh);
            } else {
                total += yhDao.updateByPrimaryKeySelective(yh);
            }
        }

        for(Integer id : yhDbMap.values()) {
            Yh deleteYh = new Yh();
            deleteYh.setId(id);
            deleteYh.setIsDeleted(true);
            yhDao.updateByPrimaryKeySelective(deleteYh);
        }
        return "成功添加" + total + "个御魂";
    }

    public List<YhCalculateVO> calculate(YhExpectVO expect) {

        long beginTime = System.currentTimeMillis();

        List<Yh> yhList = yhDao.listYh(YhSelectDTO.builder().isUsable(1).build());
        List<YhSort> yhSortList = yhSortDao.listYhSort();

        log.info("---总计耗时: " + (System.currentTimeMillis() - beginTime) / 1000 + "s.");

        return YhCalculateUtil.calculate(yhList,
                expect,
                ssDao.selectByPrimaryKey(expect.getSsId()),
                yhSortList);
    }

    public void use(List<Integer> idList, Boolean isUsable) {
        Assert.notNull(idList, "id不能为空");
        for(Integer id : idList) {
            Yh useYh = new Yh();
            useYh.setId(id);
            useYh.setIsUsable(isUsable);
            yhDao.updateByPrimaryKeySelective(useYh);
        }
    }

    public Integer allCanUse (Integer userId) {
        return yhDao.allCanUse(userId);
    }

}
